package com.wolf.vo;

import com.wolf.exception.WolfException;
import com.wolf.provider.util.JsonUtil;
import com.wolf.provider.util.StringUtils;

import java.util.*;

public class BaseResult implements java.io.Serializable {
    /**
     * 是否成功
     */
    private boolean isSucc = true;

    /**
     * 返回信息
     */
    private String message;

    /**
     * 返回对象
     */
    private Object retObject;


    public enum RETURN_TYPE {
        KEY("key"), VALUE("value"), PAIR("pair");
        private String type;

        RETURN_TYPE(String type) {
            this.type = type;
        }

        public static RETURN_TYPE parse(String type) {
            if (StringUtils.isEmpty(type)) {
                throw new WolfException("Null strings cannot be converted to enumeration type RETURN_TYP.");
            }
            for (RETURN_TYPE returnType : RETURN_TYPE.values()) {
                if (returnType.type.equalsIgnoreCase(type)) {
                    return returnType;
                }
            }
            throw new WolfException(String.format("No enum const class RETURN_TYPE.%s", type));
        }

        public boolean isEquals(RETURN_TYPE returnType) {
            if (returnType.type.equalsIgnoreCase(this.type)) {
                return true;
            }
            return false;
        }
    }

    private RETURN_TYPE returnType = RETURN_TYPE.VALUE;
    private Class tClass;

    private BaseResult() {
    }

    private BaseResult(boolean isSucc, String message) {
        this.isSucc = isSucc;
        this.message = message;
    }

    public static BaseResult getSuccess() {
        return new BaseResult();
    }

    public static BaseResult getSuccess(String message) {
        return new BaseResult(true, message);
    }

    public static BaseResult getSuccess(Object object) {
        BaseResult result = BaseResult.getSuccess();
        result.setRetObject(object);
        return result;
    }

    public <T> T getObjectResult(Class<T> tClass) {
        if (retObject == null) {
            return null;
        }

        if (isCollection()) {
            Iterator iterator = ((Collection<?>) retObject).iterator();
            if (!iterator.hasNext()) {
                return null;
            }

            if (!isSuitableClass(iterator.next(), tClass)) {
                throw new WolfException(String.format("当前的BaseResult对象包含的数据对象与Class[%s]类型不相符。", tClass.getName()));
            }

            return (T) iterator.next();
        }

        if (!isSuitableClass(retObject, tClass)) {
            throw new WolfException(String.format("当前的BaseResult对象包含的数据对象与Class[%s]类型不相符。", tClass.getName()));
        }

        return (T) retObject;
    }

    public <T> List<T> getMapResult(Class<T> tClass) {
        return getMapResult(tClass, RETURN_TYPE.VALUE);
    }

    public <T> List<T> getMapResult(Class<T> tClass, RETURN_TYPE returnType) {
        this.returnType = returnType;
        this.tClass = tClass;

        if (!(retObject instanceof Map)) {
            throw new WolfException(" 当前的BaseResult对象包含的数据对象不能转换为[java.util.Map]类型。");
        }

        List<T> emptys = new ArrayList();
        Map map = (Map) retObject;
        if (map.isEmpty()) {
            return emptys;
        }

        Iterator it = null;
        if (RETURN_TYPE.VALUE.isEquals(this.returnType)) {
            Collection values = map.values();
            it = values.iterator();

            if (!isSuitableClass(it.next(), this.tClass)) {
                throw new WolfException(String.format("当前的BaseResult对象包含的数据对象与Class[%s]类型不相符。", this.tClass.getName()));
            }
            return new ArrayList<T>(map.values());
        }

        if (RETURN_TYPE.KEY.isEquals(this.returnType)) {
            it = map.keySet().iterator();

            if (!isSuitableClass(it.next(), this.tClass)) {
                throw new WolfException(String.format("当前的BaseResult对象包含的数据对象与Class[%s]类型不相符。", this.tClass.getName()));
            }
            return new ArrayList<T>(map.keySet());
        }

        if (!Map.Entry.class.getName().equals(tClass.getName())) {
            throw new WolfException(String.format("当前的BaseResult对象包含的数据对象与Class[%s]类型不相符。", this.tClass.getName()));
        }

        ArrayList results = new ArrayList();
        Set<Map.Entry> entry = map.entrySet();
        entry.forEach(e -> {
            results.add(e);
        });
        return results;
    }

    public <T> List<T> getCollectionResult(Class<T> tClass) {

        List<T> results = new ArrayList();
        if (retObject == null) {
            return results;
        }

        if (isNonCollection()) {
            if (isSuitableClass(retObject, Map.class)) {
                return getMapResult(tClass);
            }
            throw new WolfException("当前的BaseResult对象包含的数据对象不是集合类型。");
        }

        Iterator iterator = ((Collection<?>) retObject).iterator();
        if (!iterator.hasNext()) {
            return results;
        }

        if (!isSuitableClass(iterator.next(), tClass)) {
            throw new WolfException(String.format("当前的BaseResult对象包含的数据对象与Class[%s]类型不相符。", tClass.getName()));
        }

        return new ArrayList<T>((Collection) retObject);
    }

    private boolean isNonCollection() {
        return !isCollection();
    }

    private boolean isCollection() {
        if (retObject instanceof Collection) {
            return true;
        }
        return false;
    }

    private boolean isSuitableClass(Object retObject, Class clazz) {
        if (retObject.getClass().getName() == clazz.getName()
                || clazz.isAssignableFrom(retObject.getClass())) {
            return true;
        }
        return false;
    }

    public static BaseResult getFailure(String msg, Object... args) {
        if (args != null && args.length > 0) {
            return new BaseResult(false, String.format(msg, args));
        }
        return new BaseResult(false, msg);
    }

    public boolean isEmpty() {
        if (retObject == null) {
            return true;
        }
        return false;
    }

    public boolean isNotEmpty() {
        return !isEmpty();
    }

    public boolean isSucc() {
        return isSucc;
    }

    public boolean isFailure() {
        return !isSucc;
    }

    public String getMessage() {
        return message;
    }

    private void setRetObject(Object object) {
        this.retObject = object;
    }

    private Object getRetObject() {
        return this.retObject;
    }

    public String resultToJSONString() {
        if (retObject == null) {
            return "[]";
        }
        return JsonUtil.toJSONString(retObject);
    }

    public void setSucc(boolean succ) {
        isSucc = succ;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
